#include <GameEngine/Core/Color/color_hsv.h>

#include <GameEngine/Core/Color/color.h>

#include <QtGui/QColor>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//=========================================================================================

//! Default constructor
ColorHSV::ColorHSV() : h_(0.0f), s_(0.0f), v_(0.0f) {}

//! Constructor
/*!
 @param h The hue component of the color
 @param s The saturation component of the color
 @param v The value component of the color
 */
ColorHSV::ColorHSV(float h, float s, float v) : h_(h), s_(s), v_(v) {}

//! Constructor
/*!
 @param rhs The color to copy, provided in the Qt format
 */
ColorHSV::ColorHSV(const QColor& rhs) :
	h_((float)rhs.value()/255.0f), s_((float)rhs.saturation()/255.0f), v_((float)rhs.value()/255.0f) {}

//! Copy constructor
/*!
 @param rhs The color to copy
 */
ColorHSV::ColorHSV(const ColorHSV& rhs) : h_(rhs.h_), s_(rhs.s_), v_(rhs.v_) {}

//! Assignment operator
/*!
 @param rhs The color to copy
 @return A reference to this HSV color
 */
ColorHSV& ColorHSV::operator=(const ColorHSV& rhs) {
	if ( &rhs != this ) {
		h_ = rhs.h_;
		s_ = rhs.s_;
		v_ = rhs.v_;
	}
	return *this;
}

//! Destructor
ColorHSV::~ColorHSV() {}

//! Compute the red component (read only)
/*!
 @return The computed red component
 */
float ColorHSV::r() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return red;
}

//! Compute the green component (read only)
/*!
 @return The computed green component
 */
float ColorHSV::g() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return green;
}

//! Compute the blue component (read only)
/*!
 @return The computed blue component
 */
float ColorHSV::b() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return blue;
}

//! Accessor to the alpha component (read only)
/*!
 @return Always return 1.
 */
float ColorHSV::a() const {
	return 1.0f;
}

//! Accessor to the hue component (read-write)
/*!
 @return A reference to the hue component
 */
float& ColorHSV::h() {
	return h_;
}

//! Accessor to the hue component (read only)
/*!
 @return The hue component
 */
float ColorHSV::h() const {
	return h_;
}

//! Accessor to the saturation component (read-write)
/*!
 @return A reference to the saturation component
 */
float& ColorHSV::s() {
	return s_;
}

//! Accessor to the saturation component (read only)
/*!
 @return The saturation component
 */
float ColorHSV::s() const {
	return s_;
}

//! Accessor to the value component (read-write)
/*!
 @return A reference to the value component
 */
float& ColorHSV::v() {
	return v_;
}

//! Accessor to the value component (read only)
/*!
 @return The value component
 */
float ColorHSV::v() const {
	return v_;
}

//! Test if color is achromatic (i.e., if it is a level of gray)
/*!
 @param tolerance Allows to capture "almost gray" colors
 @return True if color is achromatic, false otherwise
 */
bool ColorHSV::achromatic(float tolerance) const {
	return ( s_ <= tolerance );
}

//=========================================================================================

//! Default constructor
ColorHSVA::ColorHSVA() : h_(0.0f), s_(0.0f), v_(0.0f), a_(0.0f) {}

//! Constructor
/*!
 @param h The hue component of the color
 @param s The saturation component of the color
 @param v The value component of the color
 @param a The alpha component of the color
 */
ColorHSVA::ColorHSVA(float h, float s, float v, float a) : h_(h), s_(s), v_(v), a_(a) {}

//! Constructor
/*!
 @param rhs The color to copy, provided in the Qt format
 */
ColorHSVA::ColorHSVA(const QColor& rhs) :
	h_((float)rhs.value()/255.0f), s_((float)rhs.saturation()/255.0f), v_((float)rhs.value()/255.0f), a_((float)rhs.alpha()/255.0f) {}

//! Copy constructor
/*!
 @param rhs The color to copy
 */
ColorHSVA::ColorHSVA(const ColorHSVA& rhs) : h_(rhs.h_), s_(rhs.s_), v_(rhs.v_), a_(rhs.a_) {}

//! Assignment operator
/*!
 @param rhs The color to copy
 @return A reference to this HSVA color
 */
ColorHSVA& ColorHSVA::operator=(const ColorHSVA& rhs) {
	if ( &rhs != this ) {
		h_ = rhs.h_;
		s_ = rhs.s_;
		v_ = rhs.v_;
		a_ = rhs.a_;
	}
	return *this;
}

//! Destructor
ColorHSVA::~ColorHSVA() {}

//! Compute the red component (read only)
/*!
 @return The computed red component
 */
float ColorHSVA::r() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return red;
}

//! Compute the green component (read only)
/*!
 @return The computed green component
 */
float ColorHSVA::g() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return green;
}

//! Compute the blue component (read only)
/*!
 @return The computed blue component
 */
float ColorHSVA::b() const {
	// Quite simple for levels of gray
	if ( s_ <= 0.0f ) return v_;

	// Otherwise, full color must be converted
	float red, green, blue;
	Color::hsv_to_rgb(h_,s_,v_,red,green,blue);
	return blue;
}

//! Accessor to the alpha component (read-write)
/*!
 @return A reference to the alpha component
 */
float& ColorHSVA::a() {
	return a_;
}

//! Accessor to the alpha component (read only)
/*!
 @return The alpha component
 */
float ColorHSVA::a() const {
	return a_;
}

//! Accessor to the hue component (read-write)
/*!
 @return A reference to the hue component
 */
float& ColorHSVA::h() {
	return h_;
}

//! Accessor to the hue component (read only)
/*!
 @return The hue component
 */
float ColorHSVA::h() const {
	return h_;
}

//! Accessor to the saturation component (read-write)
/*!
 @return A reference to the saturation component
 */
float& ColorHSVA::s() {
	return s_;
}

//! Accessor to the saturation component (read only)
/*!
 @return The saturation component
 */
float ColorHSVA::s() const {
	return s_;
}

//! Accessor to the value component (read-write)
/*!
 @return A reference to the value component
 */
float& ColorHSVA::v() {
	return v_;
}

//! Accessor to the value component (read only)
/*!
 @return The value component
 */
float ColorHSVA::v() const {
	return v_;
}

//! Test if color is achromatic (i.e., if it is a level of gray)
/*!
 @param tolerance Allows to capture "almost gray" colors
 @return True if color is achromatic, false otherwise
 */
bool ColorHSVA::achromatic(float tolerance) const {
	return ( s_ <= tolerance );
}

//=========================================================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
